package com.tlgen.coopera.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.URI;
import java.util.Objects;

/*
 *@title CryptoFilter
 *@description
 *@author ta151486
 *@version 1.0
 *@create 2023/12/15 17:16
 */

/**
 * 当前类首先会解析加密后的URL
 * 当前类用于解析参数 如果参数解密后和signature不一样则返回
 * 并且会重新设定路由路径
 */
@Component
public class CryptoFilter implements Filter {

    @Autowired
    private CryptoHelper cryptoHelper;

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 从 redis 取
        String symmetricKey = "abcdefghijkl1234";
        if (symmetricKey == null) {
            System.out.println("error");
        }

        try {
            //URL动态加密  数字签名 signature
            //如果URL已加密，则解密该URL
//            String encryptedUrl = exchange.getRequest().getURI().toString();
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            String encryptedUrl = request.getRequestURI();
            String path = request.getServletPath();
            // 自定义需要进行拦截解密校验的接口, 一般是集合
            String customPath = "/request/encrypt/oXR3PxCt38WjUxpyHKn0Rtc9atH2bHO+yJ0k5uTcc9RHZ1oa1tq8PcVvKha86/Am";
            if (Objects.equals(path, customPath)) {
                String encryptPathParam = path.substring(path.indexOf("/encrypt/") + 9);
                // 使用对称密钥进行解密, 如果能解密成功, 则说明请求参数没有被篡改, 可以正常继续执行
                String decryptedPathParam = cryptoHelper.decryptUrl(encryptPathParam, symmetricKey);
                String decryptedUri = encryptedUrl.substring(0, encryptedUrl.indexOf("/encrypt/"))
                        .concat("?")
                        .concat(decryptedPathParam);
                // 解密后拿到的实际原来的 url, 使用该 url 进行内部服务请求
                URI uri = new URI(decryptedUri);
                System.out.println(uri);

                //然后得到一个signature，放在请求的末尾
                //然后对整个URL进行加密请求
                // 解析解密后的URL以获取解密的查询参数
                UriComponents uriComponents = UriComponentsBuilder.fromUriString(decryptedUri).build();
                MultiValueMap<String, String> decryptedQueryParams = uriComponents.getQueryParams();

                // 验证请求参数的签名
                String signature = decryptedQueryParams.getFirst("signature");
                if (!cryptoHelper.verifySignature(decryptedQueryParams, signature, symmetricKey)) {
                    System.out.println("error");
                }

            }

        } catch (Exception e) {
            System.out.println("error");
        }
    }
}
